在Rails中,Model之間的關聯(Associations),最容易被誤解的就是:
在每個資料表做一些什麼設定,就可以讓這幾個資料表彼此產生連結。
其實在Rails中的關聯指的是:在 Model 層級的關係上,透過 Model 所提供的一些方法(如: has_one、has_many 或 belongs_to)搭配 Rails 的資料表慣例設定主鍵(Primary Key)及外部鍵(Foreign Key),讓這些資料表串在一起。並產生一些方便實用的語法讓我們可以操作資料庫。
比較常見的資料表關聯大致有以下三種:
如下圖,我們有兩個 Model: Owner 和 Store,
每個 Owner 都有一間 Store,每間 Store 都屬於一個Owner 的ER圖,我們會畫成像下面這樣:
首先用指令建立出model
rails g model Owner name age:integer
rails g model Store title address phone owner:references
在建立Model後對owner.rb 和 store.rb兩個檔案進行關聯設定:
# app/models/owner.rb
class Owner < ApplicationRecord
has_one :store
end
Owner 會因此得到一些新的方法:
store : 找出屬於 Owner 的 Store
store= : 將 Store 指派給 Owner
build_store : 由 Owner 的角度來建立 Store 資料,需搭配 save 才能將資料寫入資料庫。
create_store : 由 Owner 的角度來建立 Store 資料並直接寫入資料庫。
belongs_to: (每間 Store 都屬於一個Owner)
# app/models/store.rb
class Store < ApplicationRecord
belongs_to :owner
end
Store 也會得到一些新的方法:
接下來讓我們加入新的Model Product
每間 Store 都有很多 Product,每個 Product 都屬於一個 Store 的ER圖,我們會畫成像下面這樣:
一樣,先用指令建立出model:
rails g model Product name price:decimal description:text store:references
# app/models/store.rb
class Store < ApplicationRecord
belongs_to :owner
has_many :products
end
Store 會因此得到一些新的方法:
products : 找出屬於 Store 的 Product
products= : 將 Product 指派給 Store,這時候要用陣列的方式來寫入資料喔!
build_store : 由 Store 的角度來建立 Product 資料,需搭配 save 才能將資料寫入資料庫。
create_store : 由 Store 的角度來建立 Product 資料並直接寫入資料庫。
belongs_to: (每間 Product 都屬於一個 Store)
# app/models/product.rb
class Product < ApplicationRecord
belongs_to :store
end
這個部分和上面雷同,請請讀者自己嘗試看看吧!
等等,每間 Store 都有很多 Product,每個 Product 都屬於一個 Store,有點不太對吧?
是的,的確不太正確應該是每間 Store 都有很多 Product,每個 Product 可以屬於多間 Store,才對。
通常在建立多對多關聯時,我們會建立一個第三方的 Model來儲存雙方的資訊:
已經很習慣了吧,先用指令建立出model:
rails g model WareHouse store:references product:references
# app/models/ware_house.rb
class WareHouse < ApplicationRecord
belongs_to :store
belongs_to :product
end
這時候設定要分長兩個部分:
首先是:
# app/models/store.rb
class Store < ApplicationRecord
belongs_to :user
has_many :ware_houses
has_many :products, through: :ware_houses
end
這邊和上面一樣,也是要設定兩個部分:
# app/models/product.rb
class Product < ApplicationRecord
has_many :ware_houses
has_many :stores, through: :ware_houses
end
大概是這樣,其他更進一步的使用方式,有機會再說吧!
鐵人賽,我們明天見!!
參考資料: